package Flap::Mailer;
use Flap qw/-b Flap::Object -m -s -w/;
use Encode;
use constant ADDR => {map{ $_ => 1 } qw/To Cc Bcc From Return-Path Reply-To/};

sub attachment {
    my($self, $att) = @_;
    $self->{attachment} = {};
    foreach(keys %$att){
        my $m = $self->Util->mime_type($_) || die qq{Can't get myme-type: "$_"};
        $self->{attachment}{$_} = [$att->{$_}, $m];
    }
    $self;
}

sub config { shift->project->config->Mailer }

sub filter {
    my $self = shift;
    my $f = shift || $self->config->filter || return $self;
    my $h = $self->{header};
    my $org = '';
    foreach my $k (sort grep{ $self->ADDR->{$_} } keys %$h){
        my(@addr, $filtered);
        foreach(split(/\s*,+\s*/, $h->{$k})){
            my $a1 = /<(.+)>/ ? $1 : $_;
            my $a2 = $self->filter_address($f, $a1)
             || die 'Invalid filter: '.$self->Util->dump_inline($f);
            $a2 eq $a1 ? push(@addr, $_) : ($filtered = push(@addr, $a2));
        }
        next if !$filtered;
        $org .= "$k: $h->{$k}\n";
        $h->{$k} = join(', ', @addr);
    }
    ${$self->{body}} .= "\n==== original header ====\n$org" if $org;
    $self;
}

sub filter_address {
    my($self, $f, $addr) = @_;
    foreach(@$f){
        if(ref $_->[0] ? ($addr =~ $_->[0]) : ($_->[0] eq '*' || $addr eq $_->[0])){
            return $_->[1] eq '*' ? $addr : $_->[1];
        }
    }
    undef;
}

sub jis_encode {
    my $self = shift;
    my $r = ref $_[0] ? shift : do{ \(my $s = shift) };
    $self->Util->fix_utf8($r);
    Encode::_utf8_on($$r);
    $$r = Encode::encode('iso-2022-jp', $$r);
}

sub mime_encode {
    my $self = shift;
    my $r = ref $_[0] ? shift : do{ \(my $s = shift) };
    $self->Util->fix_utf8($r);
    Encode::_utf8_on($$r);
    $$r = Encode::encode('MIME-Header-ISO_2022_JP', $$r);
}

sub new {
    my $self = shift->_new_({});
    my $r = $self->{body} = ref $_[0] ? shift : do{ \(my $s = shift) };
    $self->attachment(@_) if @_;
    
    my $h = $self->{header} = {};
    my $pos;
    while($$r =~ /\G([0-9a-zA-Z-]+)[ \t]*:[ \t]*(.*)\n(\n)?/g){
        $pos = $3 && pos $$r;
        my $v = $2;
        (my $k = lc($1)) =~ s/(^.|\-.)/uc($1)/eg; #Camel
        $h->{$k} = $v;
        last if $pos;
    }
    die 'Parse error' if !$pos;
    die 'No To:' if !$h->{To};
    substr($$r, 0, $pos) = '';
    -r $_ || die "$!($_)" for keys %{$self->{attachment} || {}};
    $h->{'MIME-Version'} ||= '1.0';
    $self;
}

sub sender {
    my $self = shift;
    my $h = $self->{header};
    my $addr = $h->{'Return-Path'} || $h->{From} || die 'No sender';
    $addr =~ /<(.+)>/ ? $1 : $addr;
}

sub sendmail_handle {
    my $self = shift;
    my $proj = $self->project;
    my $cfg = $self->config;
    my @s = ($cfg->sendmail, $self->sender);
    my $H;
    
    if(my $dir = $Flap::MAIL_SPOOL_DIR || $cfg->{spool_dir}){
        die "Invalid address($s[1])" if !$proj->OS->is_eml($s[1]);
        my $f = $self->spool_file($dir);
        $proj->OS->open($H, '>', $f) || die "$!($f)";
    }else{
        $proj->OS->open($H, '| %path -t -f %eml', @s) || die "$!($s[0], $s[1])";
    }
    
    $H;
}

sub spool_file {
    my($self, $dir) = @_;
    
    -w $dir || die "$!($dir)";
    my $pfx = $self->project->now->strftime('%Y%m%d_%H%M%S');
    my $i = 1;
    my $f;
    while(-f ($f = sprintf('%s/%s_%05d.eml', $dir, $pfx, $i))){
        die 'overflow' if ++$i >= 99999
    }
    $f;
}

1;
